package io.renren.modules.tms.service;

import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.utils.Constant;
import io.renren.common.utils.excel.*;
import io.renren.modules.tms.dao.TMSMapper;
import io.renren.modules.tms.entity.*;
import io.renren.modules.tms.dao.ShipmentMapper;
import io.renren.modules.tms.mapper.OrderReleaseMapper;
import io.renren.modules.tms.mapper.ShipmentEventMapper;
import io.renren.modules.tms.vo.TmsImportVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.util.TextUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Service
public class ShipmentService extends ServiceImpl<ShipmentMapper, Shipment> {

    @Resource
    private TMSMapper tmsMapper;

    @Resource
    private TmsImportLogService tmsImportLogService;

    @Resource
    private ShipmentEventMapper shipmentEventMapper;

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public ResponseMsg importExcel(MultipartFile file, int type) {
        ImportParam<TmsImportVo> param = new ImportParam<>();
        param.setFile(file);
        param.setSheetNumber(1);
        param.setImportBeanClazz(TmsImportVo.class);
        param.setHandleListener((excelData, errorInfo, handleUserName) -> {

            // 去除重复关系，防止重新查询数据库
            Map<String, String> map = new HashMap<>();

            // 运单、订单集合关系
            List<ShipmentOrder> shipmentOrderList = new ArrayList<>();
            List<ShipmentOrder> shipmentOrders;
            String shipmentNo;
            String orderNo;
            String jdeNo;

            // 当前解析行
            int line = 1;

            for (TmsImportVo excelDatum : excelData) {
                line++;
                if (excelDatum == null){
                    continue;
                }
                shipmentNo = excelDatum.getShipmentNo();
                orderNo = excelDatum.getOrderNo();
                jdeNo = excelDatum.getJdeNo();
                if (TextUtils.isBlank(shipmentNo)
                        || (TextUtils.isBlank(orderNo)
                        && TextUtils.isBlank(jdeNo))) {
                    log.error("运单/订单/jde单号为空");
                    continue;
                }
                if (!TextUtils.isBlank(excelDatum.getOrderNo())) {
                    shipmentOrders = baseMapper.selectShipmentAndOrder(shipmentNo, orderNo);
                } else {
                    shipmentOrders = baseMapper.selectShipmentAndOrder2(shipmentNo, jdeNo);
                }
                if (CollectionUtils.isEmpty(shipmentOrders)) {
                    log.error(String.format("根据运单%s及订单%s或jde单号%s未找到数据", shipmentNo, orderNo, jdeNo));
                    tmsImportLogService.insertLog(line, String.format("根据运单%s及订单%s或jde单号%s未找到数据", shipmentNo, orderNo, jdeNo));
                    continue;
                }
                for (ShipmentOrder shipmentOrder : shipmentOrders) {
                    if (shipmentOrder == null) {
                        continue;
                    }
                    String key = shipmentOrder.toString();
                    if (map.containsKey(key)) {
                        continue;
                    }
                    map.put(key, "YES");
                    shipmentOrder.setImportVo(excelDatum);
                    shipmentOrderList.add(shipmentOrder);
                }
            }

            for (ShipmentOrder shipmentOrder : shipmentOrderList) {
                if (shipmentOrder == null) {
                    continue;
                }
                if (shipmentOrder.getImportVo() == null) {
                    continue;
                }
                TmsImportVo tmsImportVo = shipmentOrder.getImportVo();
                try {
                    // 设置启运日期
                    setTime(tmsImportVo.getStartTimeDate(), tmsImportVo.getStartTime(), shipmentOrder.getSTARTTIME(),
                            shipmentOrder.getYUNDANID(), shipmentOrder.getDINGDANID(), true, line);
                    // 设置启运温度
                    setTemp(shipmentOrder, tmsImportVo.getStartTemp(), true, line);
                    // 设置到达日期
                    setTime(tmsImportVo.getEndTimeDate(), tmsImportVo.getEndTime(), shipmentOrder.getENDTIME(),
                            shipmentOrder.getYUNDANID(), shipmentOrder.getDINGDANID(), false, line);
                    // 设置到达温度
                    setTemp(shipmentOrder, tmsImportVo.getEndTemp(), false, line);
                    // 设置驾驶员
                    setDriver(shipmentOrder, tmsImportVo, line);
                    // 设置车牌号
                    setCarNo(shipmentOrder, tmsImportVo.getCarNo(), line);
                    // 设置承运商
                    setCarrier(shipmentOrder, tmsImportVo.getCarrierNo(), tmsImportVo.getCarrierName(), line);
                    // 设置运单生成日期
                    setGenerateDate(shipmentOrder, tmsImportVo.getInsertTime());
                    // 设置保温箱
                    setIncubator(shipmentOrder, tmsImportVo, line);
                } catch (Exception e) {
                    e.printStackTrace();
                    tmsImportLogService.insertLog(line, e.getLocalizedMessage());
                }
            }
        });
        param.setFileExtension(ExcelTypeEnum.XLSX);
        return EasyExcelUtil.importExcel(param);
    }

    /**
     * 设置保温箱
     *
     * @param shipmentOrder /
     * @param importVo /
     */
    private void setIncubator(ShipmentOrder shipmentOrder, TmsImportVo importVo, int line) {
        if (TextUtils.isBlank(importVo.getIncubatorNo())
                || TextUtils.isBlank(importVo.getIncubatorName())){
            return;
        }
        List<Capacity> capacity = tmsMapper.selectIncubator(importVo.getIncubatorNo(), importVo.getIncubatorName());
        if (CollectionUtils.isEmpty(capacity)){
            return;
        }
        Capacity incubator = capacity.get(0);
        if (incubator == null){
            return;
        }
        try {
            tmsMapper.updateIncubator(incubator.getId(), shipmentOrder.getYUNDANID());
        }catch (Exception e){
            log.error(String.format("更新保温箱%s无法找到对应承运商%s", importVo.getIncubatorNo(), importVo.getIncubatorName()));
            e.printStackTrace();
        }
    }

    /**
     * 设置生成日期
     *
     * @param shipmentOrder /
     * @param insertTime /
     */
    private void setGenerateDate(ShipmentOrder shipmentOrder, String insertTime) {
        if (TextUtils.isBlank(insertTime)){
            return;
        }
        tmsMapper.updateGenerateDate(shipmentOrder.getYUNDANID(), shipmentOrder.getDINGDANID(), insertTime);
    }

    /**
     * 设置承运商
     */
    private void setCarrier(ShipmentOrder shipmentOrder, String carrierNo, String carrierName, int line) {
        if (TextUtils.isBlank(carrierNo) || TextUtils.isBlank(carrierName)) {
            return;
        }
        Carrier carrier = tmsMapper.selectCarrier(carrierNo, carrierName);
        if (carrier == null) {
            log.error(String.format("根据名称及代码%s无法找到对应承运商%s", carrierNo, carrierName));
            tmsImportLogService.insertLog(line, String.format("根据名称及代码%s无法找到对应承运商%s", carrierNo, carrierName));
            return;
        }
        tmsMapper.updateCarrier(carrier.getID(), shipmentOrder.getYUNDANID());
    }

    /**
     * 设置车牌号
     */
    private void setCarNo(ShipmentOrder shipmentOrder, String carNo, int line) {
        if (TextUtils.isBlank(carNo)) {
            return;
        }
        tmsMapper.updateCarNo(carNo, shipmentOrder.getYUNDANID());
    }

    /**
     * 设置驾驶员
     */
    private void setDriver(ShipmentOrder shipmentOrder, TmsImportVo importVo, int line) {
        if (TextUtils.isBlank(importVo.getDriver()) || TextUtils.isBlank(importVo.getDriverCardNo())) {
            return;
        }
        Driver driverEntity = tmsMapper.selectDriver(importVo.getDriver(), importVo.getDriverCardNo());
        if (driverEntity == null) {
            log.error("该姓名为【" + importVo.getDriver() + "】驾驶员不存在，可能身份证号不匹配");
            tmsImportLogService.insertLog(line, "该姓名为【" + importVo.getDriver() + "】驾驶员不存在，可能身份证号不匹配");
            return;
        }
        tmsMapper.updateDriver(driverEntity.getID(), shipmentOrder.getYUNDANID());
    }

    private void setTemp(ShipmentOrder shipmentOrder, String temp, boolean isStart, int line) {
        if (TextUtils.isBlank(temp)) {
            return;
        }
        if (Constant.TMS_IMPORT_TYPE.RESET.equals(temp)){
            if (isStart) {
                tmsMapper.resetShipEventStartTemp(shipmentOrder.getYUNDANID());
                tmsMapper.resetOrderStartTemp(shipmentOrder.getDINGDANID());
            } else {
                tmsMapper.resetShipEventEndTemp(shipmentOrder.getYUNDANID());
                tmsMapper.resetOrderEndTemp(shipmentOrder.getDINGDANID());
            }
        }else {
            if (isStart) {
                tmsMapper.updateShipEventStartTemp(temp, shipmentOrder.getYUNDANID());
                tmsMapper.updateOrderStartTemp(temp, shipmentOrder.getDINGDANID());
            } else {
                tmsMapper.updateShipEventEndTemp(temp, shipmentOrder.getYUNDANID());
                tmsMapper.updateOrderEndTemp(temp, shipmentOrder.getDINGDANID());
            }
        }
    }

    /**
     * 设置时间
     *
     * @param monthTime
     * @param dayTime
     * @param originalDate
     * @param yunDanId
     * @param dingDanId
     * @param isStart 是否启运
     * @param line
     */
    private void setTime(String monthTime, String dayTime, Date originalDate,
                         String yunDanId, String dingDanId, boolean isStart, int line) {
        if (TextUtils.isBlank(monthTime) && TextUtils.isBlank(dayTime)) {
            return;
        }
        // 如果是重置时间
        if (Constant.TMS_IMPORT_TYPE.RESET.equals(monthTime)
                && Constant.TMS_IMPORT_TYPE.RESET.equals(dayTime)){
            if (isStart) {
                tmsMapper.updateShipStartTime(null, yunDanId);
                tmsMapper.updateShipEventStartTime(null, yunDanId);
            } else {
                tmsMapper.updateShipEndTime(null, yunDanId);
                tmsMapper.updateShipEventEndTime(null, yunDanId);
                tmsMapper.updateOrderEndTime(null, dingDanId);
            }
            return;
        }
        String date = null;
        String time = null;
        // 同时设置日期和时间
        if (!TextUtils.isBlank(monthTime) && !TextUtils.isBlank(dayTime)) {
            date = getDate(monthTime);
            time = getTime(dayTime);
        }
        // 单独设置日期
        else if (!TextUtils.isBlank(monthTime)) {
            if (originalDate == null) {
                log.error("因原订单无对应时间，而导入数据也只设置了【日期】，未设置【时间】，故无法形成时间戳");
                tmsImportLogService.insertLog(line, "因原订单无对应时间，而导入数据也只设置了【日期】，未设置【时间】，故无法形成时间戳");
                return;
            }
            date = getDate(monthTime);
            time = DateUtil.format(originalDate, "HH:mm:ss");
        }
        // 单独设置时间
        else if (!TextUtils.isBlank(dayTime)) {
            if (originalDate == null) {
                log.error("因原订单无对应时间，而导入数据也只设置了【时间】，未设置【日期】，故无法形成时间戳");
                tmsImportLogService.insertLog(line, "因原订单无对应时间，而导入数据也只设置了【时间】，未设置【日期】，故无法形成时间戳");
                return;
            }
            date = DateUtil.format(originalDate, "yyyy-MM-dd");
            time = getTime(dayTime);
        }
        // 查找运输事件是否存在
        if (isStart) {
            int count = tmsMapper.selectShipEvent(yunDanId, Constant.TMS_EVENT_TYPE.DEPARTURE);
            tmsMapper.updateShipStartTime(date + " " + time, yunDanId);
            if (count > 0) {
                tmsMapper.updateShipEventStartTime(date + " " + time, yunDanId);
            }else {
                insertEvent(yunDanId, date, time, Constant.TMS_EVENT_TYPE.DEPARTURE);
            }
        } else {
            int count = tmsMapper.selectShipEvent(yunDanId, Constant.TMS_EVENT_TYPE.ARRIVE);
            tmsMapper.updateShipEndTime(date + " " + time, yunDanId);
            tmsMapper.updateOrderEndTime(date + " " + time, dingDanId);
            if (count > 0) {
                tmsMapper.updateShipEventEndTime(date + " " + time, yunDanId);
            }else {
                insertEvent(yunDanId, date, time, Constant.TMS_EVENT_TYPE.ARRIVE);
            }
        }
    }

    @Transactional
    public void insertEvent(String yunDanId, String date, String time, String eventType) {

        int id = shipmentEventMapper.selectLastId() + 1;

        ShipmentEvent shipmentEvent = new ShipmentEvent();
        shipmentEvent.setId(id);
        shipmentEvent.setShipment(Integer.valueOf(yunDanId));
        shipmentEvent.setEventType(eventType);
        shipmentEvent.setReport("YZJ-TMS");
        try {
            shipmentEvent.setReportTime(sdf.parse(date + " " + time));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        shipmentEvent.setDomainName("DEFAULT");
        shipmentEvent.setVersion(0);
        shipmentEvent.setInsertUser("DEFAULT.ADMIN");
        shipmentEvent.setInsertDate(new Date());
        shipmentEventMapper.insert(shipmentEvent);
    }

    private String getDate(String timeImportVo) {
        String[] dateArray = timeImportVo.split("/");
        if (dateArray.length <= 1){
            dateArray = timeImportVo.split("-");
        }
        if (dateArray.length <= 1){
            throw new IllegalArgumentException("date日期格式存在问题，非-或者/划分");
        }
        return String.format("%s-%s-%s", dateArray[0], dateArray[1], dateArray[2]);
    }

    private String getTime(String timeInput) {
        String[] timeArray = timeInput.replace("：", ":").split(":");
        String time = "";
        if (timeArray.length > 0) {
            time += toIntStr(timeArray[0]) + ":";
        } else {
            time += "00:";
        }
        if (timeArray.length > 1) {
            time += toIntStr(timeArray[1]) + ":";
        } else {
            time += "00:";
        }
        if (timeArray.length > 2) {
            time += toIntStr(timeArray[2]);
        } else {
            time += "00";
        }
        return time;
    }

    private String toIntStr(String number) {
        int count = Integer.parseInt(number);
        return count < 10 ? "0" + count : "" + count;
    }
}
